package com.example.jetpack.flowTest

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.withContext


suspend fun flow1() {
    flow<Int> {
        (0..4).forEach {
            emit(it)                //生产者消费数据
        }
    }.collect {
        println(it)             //消费者处理数据
    }
}

// 流是冷的，collect 被调用用 flow 内的方法体才会被调用
// 流构建器： flowOf  asFlow()
// 中间操作符： map  transform  take
// 末端操作符： toList  toSet  first reduce
// 缓存操作符： buffer
// 组合流操作符： conflate
// 处理最后一条数据  ： collectLast
// 合并操作符： zip
// flow catch 只能捕获生产者异常，不能捕获消费者异常
// onCompletion 流发送完成后可以再发送一个值
suspend fun a() {

    //zip ：合并两条流的数据再发送，长度不一致时，按短的处理
    val flow_1 = (1..3).asFlow()
    val flow2 = flowOf("张san","李四","王五")
    flow_1.zip(flow2){ a,b ->
        "$a : $b"
    }.collect { println(it) }

    //collectLast : 生产者数据已经发射过来，但消费者还没有处理完上一个数据，直接停止处理上一条数据，直接处理最新的数据
    flow<Int> { (1..9).forEach {
        delay(100)
        emit(it)
    }  }.collectLatest {
        delay(800)
        println(it)
    }


    //conflate ： 当生产者发射速度大于消费者的时候,消费者只能拿到涩生产者最新的发射的数据
    flow<Int> { (1..9).forEach {
        delay(100)
        emit(it)
    }  }.conflate().collect {
        delay(300)
        println(it)
    }

    //buffer 缓存生产者数据，不会被消费者阻塞
    val startMills = System.currentTimeMillis()
    flow<Int> { (1..3).forEach{
        delay(300)
        emit(it)
    }
    }.buffer(4)
        .collect {
            delay(400)
            println(it)
            println("时间花销： ${System.currentTimeMillis() - startMills }  ")
        }



    //toList 把数据消费到一个list中
   val x =  (1..9).asFlow().filter { it % 2 ==0 }.toList()
    //获取第一个元素
   val y =  (1..9).asFlow().filter { it % 2 ==0 }.first()
    //reduce : 提供运算公式负责计算
    (1..9).asFlow().reduce { accumulator, value ->
        println("$accumulator: $value")
        accumulator + value
    }

    //限长操作符： take,限制消费的代码 take(3):只有前三个能别消费
    (1..9).asFlow().take(3).collect { println(it) }

    //类型转换 ： transform 泛型表示将前一个类型转换为后一个类型
    (1..3).asFlow().transform<Int,String> { value ->
        emit("xxxxxx transform Int to String $value")
    }.collect {
         println(it)
    }

    //操作符  flowof :  将flowOf内的可变长参数一一发射
    val a = flowOf(1, 3, 4, 5, 6)
    a.collect {
        println(it)
    }
    //asFlow() 将集合装换为flow发射
    listOf(1, 2, 3, 4, 5).asFlow().collect {
        println(it)
    }
    // 过渡符： map 在其中进行一些过度操作，将生产者发送的数据*9后再发射
    (1..9).asFlow().map {
        it * 9
    }.collect { println(it) }
    // map 中可以进行异步操作
    flow<Int> {
        var userId = login()
        userId
    }.map {
        var permission = getPermission(it)
        permission
    }.collect { println("$it") }

}

private suspend fun login(): Int {
    return withContext(Dispatchers.IO) {
        return@withContext 1
    }
}

private suspend fun getPermission(value : Int): Int {
    return withContext(Dispatchers.IO) {
        return@withContext 1
    }
}


class FlowLearn {
}